#ifndef MAMBA_SERVICE_MESSENGER_COMET_CONTENT_HPP
#define MAMBA_SERVICE_MESSENGER_COMET_CONTENT_HPP

#include <fstream>
#include <map>
#include <fas/misc/http/ad_uri.hpp>
#include <fas/misc/http/uri/uri_processor.hpp>
#include <fas/misc/http/uri/rules/rule_substr.hpp>

#include <fas/adv/asp/http/tags.hpp>

namespace fasys{ namespace sservice{

namespace aa = ::fas::aop;
namespace ap = ::fas::pattern;
namespace ah = ::fas::http;
namespace ahi = ::fas::http::uri;
namespace adah = ::fas::adv::asp::http;

struct _content_ready_{};
struct _json_rpc_ready_{};

struct rule_content { const char* value() { return "/_n_o_t_i_f_y_/messenger"; } };
struct rule_json_rpc { const char* value() { return "/_n_o_t_i_f_y_/json_rpc"; } };

typedef ap::type_list_n<
  aa::advice< ahi::ad_rule< _content_ready_, ahi::rule_substr< rule_content > > >,
  aa::advice< ahi::ad_rule< _json_rpc_ready_, ahi::rule_substr< rule_json_rpc > > >
>::type rule_list;

struct uri_processor: ahi::uri_processor< aa::aspect< rule_list > > {};

struct ad_uri: ah::ad_uri< uri_processor > {};

struct ad_content
{
  std::string content_path;
  std::map<std::string, std::string> content_map;

  template<typename T, typename H, typename B>
  void operator()(T& t, H& h, B& b )
  {
    std::string uri = h.initial().get_uri(); // h.
    std::string::size_type pos = uri.find('?');
    std::string path = uri.substr(0, pos);
    std::cout << "path = " << path << std::endl;
    if ( content_path.empty() )
      path = "." + path;
    else
      path = content_path + path;

    std::map<std::string, std::string>::iterator itr = content_map.find(path);
    if ( itr == content_map.end() )
    {
      std::string content;
      std::ifstream f( path.c_str() );
      std::copy(
        std::istreambuf_iterator<char>(f),
        std::istreambuf_iterator<char>(),
        std::back_inserter(content)
      );
      content_map[path] = content;
      t.get_aspect().template get< adah::_outgoing_ >()(t, content.c_str(), content.size() );
    }
    else
    {
      t.get_aspect().template get< adah::_outgoing_ >()(t, itr->second.c_str(), itr->second.size() );
      // content = content_map[path];
    }

    t.release();
  }
};

struct ad_welcome
{
private:
  const char* data;
  size_t size;
public:
  ad_welcome(): data(0), size(0) {}

  void set_data(const char* d, size_t s)
  {
    data = d;
    size = s;
  }
  
  template<typename T, typename H, typename B>
  void operator()(T& t, H& h, B& b )
  {
    t.get_aspect().template get< adah::_outgoing_  >()(t, data, size );
  }

};

struct ad_json_rpc
{
  template<typename T, typename H, typename B>
  void operator()(T& t, H& h, B& b )
  {
    t.get_aspect().template get< adah::_pre_incoming_>()(t, h, b );
  }
};

struct uri_advice:
  aa::advice< ah::_body_readed_, ad_uri >
{
};

struct content_advice:
  aa::advice< _content_ready_, ad_content >
{
};

struct json_rpc_advice:
  aa::advice< _json_rpc_ready_, ad_json_rpc >
{
};

struct welcome_advice:
  aa::advice< ah::_default_uri_ready_, ad_welcome >
{
};


}}

#endif
